package com.hzya.frame.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpMessage;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.protocol.HTTP;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;

/**
 * SM2请求加解密实例
 * 这个类现在通过构造函数接收所有配置
 *
 * @author liuyang
 */
public class CbsApiHandler {

    private final String bodyEncryptionKey;
    private final String signEncryptionPrivateKey;
    private final String bodyDecryptionKey;
    private final String token;
    private final String targetUrl;
    private final byte[] requestDataBytes;

    /**
     * @param targetUrl                业务接口URL
     * @param token                    认证Token (不含"Bearer ")
     * @param bodyEncryptionKey        平台公钥
     * @param signEncryptionPrivateKey 企业签名私钥
     * @param bodyDecryptionKey        企业解密私钥
     * @param requestDataBytes         请求体字节数组 (来自FlowFile)
     */
    public CbsApiHandler(String targetUrl, String token, String bodyEncryptionKey, String signEncryptionPrivateKey, String bodyDecryptionKey, byte[] requestDataBytes) {
        this.targetUrl = targetUrl;
        this.token = token;
        this.bodyEncryptionKey = bodyEncryptionKey;
        this.signEncryptionPrivateKey = signEncryptionPrivateKey;
        this.bodyDecryptionKey = bodyDecryptionKey;
        this.requestDataBytes = requestDataBytes;
    }

    /**
     * 根据实例配置生成请求报文
     */
    public HttpPost setupRequest() {
        long timestamp = System.currentTimeMillis();

        // 请求数据拼接：报文体+时间戳
        byte[] timestampBytes = ("&timestamp=" + timestamp).getBytes(StandardCharsets.UTF_8);
        byte[] newBytes = new byte[requestDataBytes.length + timestampBytes.length];
        System.arraycopy(requestDataBytes, 0, newBytes, 0, requestDataBytes.length);
        System.arraycopy(timestampBytes, 0, newBytes, requestDataBytes.length, timestampBytes.length);

        // 生成签名
        byte[] signature = SM2Util.sign(this.signEncryptionPrivateKey, newBytes);
        String sign = Base64.encodeBase64String(SM2Util.encodeDERSignature(signature));

        // 设置请求URL和请求头
        HttpPost httpPost = new HttpPost(this.targetUrl);
        httpPost.setHeader(Constants.SIGN_HEADER_NAME, sign);
        httpPost.setHeader(Constants.TIMESTAMP_HEADER, Long.toString(timestamp));
        httpPost.setHeader(HTTP.CONTENT_TYPE, Constants.TARGET_CONTENT_TYPE);
        httpPost.setHeader(Constants.AUTHORIZATION, Constants.BEARER + this.token);

        // 报文体加密并设置
        byte[] encryptedData = SM2Util.encrypt(this.bodyEncryptionKey, requestDataBytes);
        httpPost.setEntity(new ByteArrayEntity(encryptedData));

        return httpPost;
    }

    /**
     * 根据实例配置处理响应报文
     */
    public byte[] handleResponse(HttpResponse response) throws Exception {
        InputStream content = response.getEntity().getContent();
        byte[] responseData = IOUtils.toByteArray(content);

        if (responseData == null || responseData.length == 0) {
            return new byte[0];
        }

        if (getHeader(response, Constants.ENCRYPTION_ENABLED_HEADER_NAME)) {
            responseData = SM2Util.decrypt(this.bodyDecryptionKey, responseData);
        }

        if (getHeader(response, Constants.X_MBCLOUD_COMPRESS)) {
            responseData = decompress(responseData);
        }
        return responseData;
    }

    private boolean getHeader(HttpMessage message, String name) {
        Header header = message.getFirstHeader(name);
        return header != null;
    }

    private byte[] decompress(byte[] data) throws IOException {
        ByteArrayInputStream input = new ByteArrayInputStream(data);
        GZIPInputStream gzipInput = new GZIPInputStream(input);
        return IOUtils.toByteArray(gzipInput);
    }
}